package com.qfmy.config;

import com.alibaba.fastjson2.support.spring.data.redis.FastJsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @ClassName: RedisConfigs
 * @author： zhengjt
 * @data： 2021/9/23 20:18
 * @version：1.0
 * @描述： Redis的配置类
 *      序列化方式：  1、GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
 *                   2、Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
 *                   3、JacksonJsonRedisSerializer: 序列化object对象为json字符串
 *                   4、JdkSerializationRedisSerializer: 序列化java对象（默认）
 *                   5、StringRedisSerializer: 简单的字符串序列化
 */
@Configuration
public class RedisConfigs {

    /**
     * 设置Redis序列化方式，默认使用的JDKSerializer的序列化方式，效率低，
     * 此处使用 Jackson2JsonRedisSerializer
     *
     * @param factory
     * @return
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        //  设置连接工厂
        redisTemplate.setConnectionFactory(factory);

        //  对象序列化方式： Jackson2JsonRedisSerializer
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
//        FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        // 指定要序列化的域，field,get和set,以及修饰符范围，ANY是都有包括private和public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        /// 方法过期，改为下面代码
//        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        // 指定序列化输入的类型，类必须是非final修饰的，final修饰的类，比如String,Integer等会抛出异常
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        serializer.setObjectMapper(objectMapper);
        /// 重复代码（暂时注释，防止出错，如有需要，重新放开）
//        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //  字符串序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //  设置key的序列化需要采用StringRedisSerializer；
        //  设置value的序列化需要采用 对象序列化方式（Jackson2JsonRedisSerializer/FastJsonRedisSerializer）
        // key的序列化类型
        redisTemplate.setKeySerializer(stringRedisSerializer);
        // value的序列化类型
        redisTemplate.setValueSerializer(serializer);
        // Hash key序列化
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        // Hash value序列化
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}
